home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 2000 October / Software of the Month - Ultimate Collection Shareware 277.iso / pc / PROGRAMS / UTILITY / WINLINUX / DATA1.CAB / programs_-_kernel_source / FS / DQUOT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1999-09-17  |  35.0 KB  |  1,444 lines

  1. /*
  2.  * Implementation of the diskquota system for the LINUX operating
  3.  * system. QUOTA is implemented using the BSD system call interface as
  4.  * the means of communication with the user level. Currently only the
  5.  * ext2 filesystem has support for disk quotas. Other filesystems may
  6.  * be added in the future. This file contains the generic routines
  7.  * called by the different filesystems on allocation of an inode or
  8.  * block. These routines take care of the administration needed to
  9.  * have a consistent diskquota tracking system. The ideas of both
  10.  * user and group quotas are based on the Melbourne quota system as
  11.  * used on BSD derived systems. The internal implementation is 
  12.  * based on one of the several variants of the LINUX inode-subsystem
  13.  * with added complexity of the diskquota system.
  14.  * 
  15.  * Version: $Id: dquot.c,v 6.3 1996/11/17 18:35:34 mvw Exp mvw $
  16.  * 
  17.  * Author:    Marco van Wieringen <mvw@planets.elm.net>
  18.  *
  19.  * Fixes:   Dmitry Gorodchanin <pgmdsg@ibi.com>, 11 Feb 96
  20.  *
  21.  *        Revised list management to avoid races
  22.  *        -- Bill Hawes, <whawes@star.net>, 9/98
  23.  *
  24.  * (C) Copyright 1994 - 1997 Marco van Wieringen 
  25.  */
  26.  
  27. #include <linux/errno.h>
  28. #include <linux/kernel.h>
  29. #include <linux/sched.h>
  30.  
  31. #include <linux/types.h>
  32. #include <linux/string.h>
  33. #include <linux/fcntl.h>
  34. #include <linux/stat.h>
  35. #include <linux/tty.h>
  36. #include <linux/file.h>
  37. #include <linux/malloc.h>
  38. #include <linux/mount.h>
  39. #include <linux/smp.h>
  40. #include <linux/smp_lock.h>
  41. #include <linux/init.h>
  42. #include <linux/slab.h>
  43.  
  44. #include <asm/uaccess.h>
  45.  
  46. #define __DQUOT_VERSION__    "dquot_6.4.0"
  47.  
  48. int nr_dquots = 0, nr_free_dquots = 0;
  49. int max_dquots = NR_DQUOTS;
  50.  
  51. static char quotamessage[MAX_QUOTA_MESSAGE];
  52. static char *quotatypes[] = INITQFNAMES;
  53.  
  54. static kmem_cache_t *dquot_cachep;
  55.  
  56. /*
  57.  * Dquot List Management:
  58.  * The quota code uses three lists for dquot management: the inuse_list,
  59.  * free_dquots, and dquot_hash[] array. A single dquot structure may be
  60.  * on all three lists, depending on its current state.
  61.  *
  62.  * All dquots are placed on the inuse_list when first created, and this
  63.  * list is used for the sync and invalidate operations, which must look
  64.  * at every dquot.
  65.  *
  66.  * Unused dquots (dq_count == 0) are added to the free_dquots list when
  67.  * freed, and this list is searched whenever we need an available dquot.
  68.  * Dquots are removed from the list as soon as they are used again, and
  69.  * nr_free_dquots gives the number of dquots on the list.
  70.  *
  71.  * Dquots with a specific identity (device, type and id) are placed on
  72.  * one of the dquot_hash[] hash chains. The provides an efficient search
  73.  * mechanism to lcoate a specific dquot.
  74.  */
  75.  
  76. static struct dquot *inuse_list = NULL;
  77. LIST_HEAD(free_dquots);
  78. static struct dquot *dquot_hash[NR_DQHASH];
  79. static int dquot_updating[NR_DQHASH];
  80.  
  81. static struct dqstats dqstats;
  82. static struct wait_queue *dquot_wait = (struct wait_queue *)NULL,
  83.                          *update_wait = (struct wait_queue *)NULL;
  84.  
  85. static inline char is_enabled(struct vfsmount *vfsmnt, short type)
  86. {
  87.     switch (type) {
  88.         case USRQUOTA:
  89.             return((vfsmnt->mnt_dquot.flags & DQUOT_USR_ENABLED) != 0);
  90.         case GRPQUOTA:
  91.             return((vfsmnt->mnt_dquot.flags & DQUOT_GRP_ENABLED) != 0);
  92.     }
  93.     return(0);
  94. }
  95.  
  96. static inline char sb_has_quota_enabled(struct super_block *sb, short type)
  97. {
  98.     struct vfsmount *vfsmnt;
  99.  
  100.     return((vfsmnt = lookup_vfsmnt(sb->s_dev)) != (struct vfsmount *)NULL && is_enabled(vfsmnt, type));
  101. }
  102.  
  103. static inline char dev_has_quota_enabled(kdev_t dev, short type)
  104. {
  105.     struct vfsmount *vfsmnt;
  106.  
  107.     return((vfsmnt = lookup_vfsmnt(dev)) != (struct vfsmount *)NULL && is_enabled(vfsmnt, type));
  108. }
  109.  
  110. static inline int const hashfn(kdev_t dev, unsigned int id, short type)
  111. {
  112.     return((HASHDEV(dev) ^ id) * (MAXQUOTAS - type)) % NR_DQHASH;
  113. }
  114.  
  115. static inline void insert_dquot_hash(struct dquot *dquot)
  116. {
  117.     struct dquot **htable;
  118.  
  119.     htable = &dquot_hash[hashfn(dquot->dq_dev, dquot->dq_id, dquot->dq_type)];
  120.     if ((dquot->dq_hash_next = *htable) != NULL)
  121.         (*htable)->dq_hash_pprev = &dquot->dq_hash_next;
  122.     *htable = dquot;
  123.     dquot->dq_hash_pprev = htable;
  124. }
  125.  
  126. static inline void hash_dquot(struct dquot *dquot)
  127. {
  128.     insert_dquot_hash(dquot);
  129. }
  130.  
  131. static inline void unhash_dquot(struct dquot *dquot)
  132. {
  133.     if (dquot->dq_hash_pprev) {
  134.         if (dquot->dq_hash_next)
  135.             dquot->dq_hash_next->dq_hash_pprev = dquot->dq_hash_pprev;
  136.         *(dquot->dq_hash_pprev) = dquot->dq_hash_next;
  137.         dquot->dq_hash_pprev = NULL;
  138.     }
  139. }
  140.  
  141. static inline struct dquot *find_dquot(unsigned int hashent, kdev_t dev, unsigned int id, short type)
  142. {
  143.     struct dquot *dquot;
  144.  
  145.     for (dquot = dquot_hash[hashent]; dquot; dquot = dquot->dq_hash_next)
  146.         if (dquot->dq_dev == dev && dquot->dq_id == id && dquot->dq_type == type)
  147.             break;
  148.     return dquot;
  149. }
  150.  
  151. /* Add a dquot to the head of the free list */
  152. static inline void put_dquot_head(struct dquot *dquot)
  153. {
  154.     list_add(&dquot->dq_free, &free_dquots);
  155.     nr_free_dquots++;
  156. }
  157.  
  158. /* Add a dquot to the tail of the free list */
  159. static inline void put_dquot_last(struct dquot *dquot)
  160. {
  161.     list_add(&dquot->dq_free, free_dquots.prev);
  162.     nr_free_dquots++;
  163. }
  164.  
  165. static inline void remove_free_dquot(struct dquot *dquot)
  166. {
  167.     /* sanity check */
  168.     if (list_empty(&dquot->dq_free)) {
  169.         printk("remove_free_dquot: dquot not on free list??\n");
  170.     }
  171.     list_del(&dquot->dq_free);
  172.     INIT_LIST_HEAD(&dquot->dq_free);
  173.     nr_free_dquots--;
  174. }
  175.  
  176. static inline void put_inuse(struct dquot *dquot)
  177. {
  178.     if ((dquot->dq_next = inuse_list) != NULL)
  179.         inuse_list->dq_pprev = &dquot->dq_next;
  180.     inuse_list = dquot;
  181.     dquot->dq_pprev = &inuse_list;
  182. }
  183.  
  184. #if 0    /* currently not needed */
  185. static inline void remove_inuse(struct dquot *dquot)
  186. {
  187.     if (dquot->dq_pprev) {
  188.         if (dquot->dq_next)
  189.             dquot->dq_next->dq_pprev = dquot->dq_pprev;
  190.         *dquot->dq_pprev = dquot->dq_next;
  191.         dquot->dq_pprev = NULL;
  192.     }
  193. }
  194. #endif
  195.  
  196. static void __wait_on_dquot(struct dquot *dquot)
  197. {
  198.     struct wait_queue wait = { current, NULL };
  199.  
  200.     add_wait_queue(&dquot->dq_wait, &wait);
  201. repeat:
  202.     current->state = TASK_UNINTERRUPTIBLE;
  203.     if (dquot->dq_flags & DQ_LOCKED) {
  204.         schedule();
  205.         goto repeat;
  206.     }
  207.     remove_wait_queue(&dquot->dq_wait, &wait);
  208.     current->state = TASK_RUNNING;
  209. }
  210.  
  211. static inline void wait_on_dquot(struct dquot *dquot)
  212. {
  213.     if (dquot->dq_flags & DQ_LOCKED)
  214.         __wait_on_dquot(dquot);
  215. }
  216.  
  217. static inline void lock_dquot(struct dquot *dquot)
  218. {
  219.     wait_on_dquot(dquot);
  220.     dquot->dq_flags |= DQ_LOCKED;
  221. }
  222.  
  223. static inline void unlock_dquot(struct dquot *dquot)
  224. {
  225.     dquot->dq_flags &= ~DQ_LOCKED;
  226.     wake_up(&dquot->dq_wait);
  227. }
  228.  
  229. static void write_dquot(struct dquot *dquot)
  230. {
  231.     short type = dquot->dq_type;
  232.     struct file *filp = dquot->dq_mnt->mnt_dquot.files[type];
  233.     mm_segment_t fs;
  234.     loff_t offset;
  235.     ssize_t ret;
  236.  
  237.     lock_dquot(dquot);
  238.     down(&dquot->dq_mnt->mnt_dquot.semaphore);
  239.     offset = dqoff(dquot->dq_id);
  240.     fs = get_fs();
  241.     set_fs(KERNEL_DS);
  242.  
  243.     /*
  244.      * Note: clear the DQ_MOD flag unconditionally,
  245.      * so we don't loop forever on failure.
  246.      */
  247.     dquot->dq_flags &= ~DQ_MOD;
  248.     ret = 0;
  249.     if (filp)
  250.         ret = filp->f_op->write(filp, (char *)&dquot->dq_dqb, 
  251.                     sizeof(struct dqblk), &offset);
  252.     if (ret != sizeof(struct dqblk))
  253.         printk(KERN_WARNING "VFS: dquota write failed on dev %s\n",
  254.             kdevname(dquot->dq_dev));
  255.  
  256.     up(&dquot->dq_mnt->mnt_dquot.semaphore);
  257.     set_fs(fs);
  258.  
  259.     unlock_dquot(dquot);
  260.     dqstats.writes++;
  261. }
  262.  
  263. static void read_dquot(struct dquot *dquot)
  264. {
  265.     short type;
  266.     struct file *filp;
  267.     mm_segment_t fs;
  268.     loff_t offset;
  269.  
  270.     type = dquot->dq_type;
  271.     filp = dquot->dq_mnt->mnt_dquot.files[type];
  272.  
  273.     if (filp == (struct file *)NULL)
  274.         return;
  275.  
  276.     lock_dquot(dquot);
  277.     down(&dquot->dq_mnt->mnt_dquot.semaphore);
  278.     offset = dqoff(dquot->dq_id);
  279.     fs = get_fs();
  280.     set_fs(KERNEL_DS);
  281.     filp->f_op->read(filp, (char *)&dquot->dq_dqb, sizeof(struct dqblk), &offset);
  282.     up(&dquot->dq_mnt->mnt_dquot.semaphore);
  283.     set_fs(fs);
  284.  
  285.     if (dquot->dq_bhardlimit == 0 && dquot->dq_bsoftlimit == 0 &&
  286.         dquot->dq_ihardlimit == 0 && dquot->dq_isoftlimit == 0)
  287.         dquot->dq_flags |= DQ_FAKE;
  288.     unlock_dquot(dquot);
  289.     dqstats.reads++;
  290. }
  291.  
  292. /*
  293.  * Unhash and selectively clear the dquot structure,
  294.  * but preserve the use count, list pointers, and
  295.  * wait queue.
  296.  */
  297. void clear_dquot(struct dquot *dquot)
  298. {
  299.     /* unhash it first */
  300.         unhash_dquot(dquot);
  301.         dquot->dq_mnt = NULL;
  302.         dquot->dq_flags = 0;
  303.         dquot->dq_referenced = 0;
  304.         memset(&dquot->dq_dqb, 0, sizeof(struct dqblk));
  305. }
  306.  
  307. void invalidate_dquots(kdev_t dev, short type)
  308. {
  309.     struct dquot *dquot, *next = inuse_list;
  310.     int need_restart;
  311.  
  312. restart:
  313.     need_restart = 0;
  314.     while ((dquot = next) != NULL) {
  315.         next = dquot->dq_next;
  316.         if (dquot->dq_dev != dev)
  317.             continue;
  318.         if (dquot->dq_type != type)
  319.             continue;
  320.         if (dquot->dq_flags & DQ_LOCKED) {
  321.             __wait_on_dquot(dquot);
  322.  
  323.             /* Set the flag for another pass. */
  324.             need_restart = 1;
  325.             /*
  326.              * Make sure it's still the same dquot.
  327.              */
  328.             if (dquot->dq_dev != dev)
  329.                 continue;
  330.             if (dquot->dq_type != type)
  331.                 continue;
  332.         }
  333.         clear_dquot(dquot);
  334.     }
  335.     /*
  336.      * If anything blocked, restart the operation
  337.      * to ensure we don't miss any dquots.
  338.      */ 
  339.     if (need_restart)
  340.         goto restart;
  341. }
  342.  
  343. int sync_dquots(kdev_t dev, short type)
  344. {
  345.     struct dquot *dquot, *next = inuse_list;
  346.     int need_restart;
  347.  
  348. restart:
  349.     need_restart = 0;
  350.     while ((dquot = next) != NULL) {
  351.         next = dquot->dq_next;
  352.         if (dev && dquot->dq_dev != dev)
  353.             continue;
  354.                 if (type != -1 && dquot->dq_type != type)
  355.             continue;
  356.         if (!(dquot->dq_flags & (DQ_LOCKED | DQ_MOD)))
  357.             continue;
  358.  
  359.         wait_on_dquot(dquot);
  360.         if (dquot->dq_flags & DQ_MOD)
  361.             write_dquot(dquot);
  362.         /* Set the flag for another pass. */
  363.         need_restart = 1;
  364.     }
  365.     /*
  366.      * If anything blocked, restart the operation
  367.      * to ensure we don't miss any dquots.
  368.      */ 
  369.     if (need_restart)
  370.         goto restart;
  371.  
  372.     dqstats.syncs++;
  373.     return(0);
  374. }
  375.  
  376. void dqput(struct dquot *dquot)
  377. {
  378.     if (!dquot)
  379.         return;
  380.     if (!dquot->dq_count) {
  381.         printk("VFS: dqput: trying to free free dquot\n");
  382.         printk("VFS: device %s, dquot of %s %d\n",
  383.             kdevname(dquot->dq_dev), quotatypes[dquot->dq_type],
  384.             dquot->dq_id);
  385.         return;
  386.     }
  387.  
  388.     /*
  389.      * If the dq_mnt pointer isn't initialized this entry needs no
  390.      * checking and doesn't need to be written. It's just an empty
  391.      * dquot that is put back on to the freelist.
  392.      */
  393.     if (dquot->dq_mnt != (struct vfsmount *)NULL) {
  394.         dqstats.drops++;
  395. we_slept:
  396.         wait_on_dquot(dquot);
  397.         if (dquot->dq_count > 1) {
  398.             dquot->dq_count--;
  399.             return;
  400.         }
  401.         if (dquot->dq_flags & DQ_MOD) {
  402.             write_dquot(dquot);
  403.             goto we_slept;
  404.         }
  405.     }
  406.  
  407.     /* sanity check */
  408.     if (!list_empty(&dquot->dq_free)) {
  409.         printk("dqput: dquot already on free list??\n");
  410.     }
  411.     if (--dquot->dq_count == 0) {
  412.          /* Place at end of LRU free queue */
  413.         put_dquot_last(dquot);
  414.         wake_up(&dquot_wait);
  415.     }
  416.  
  417.     return;
  418. }
  419.  
  420. static void grow_dquots(void)
  421. {
  422.     struct dquot *dquot;
  423.     int cnt = 32;
  424.  
  425.     while (cnt > 0) {
  426.         dquot = kmem_cache_alloc(dquot_cachep, SLAB_KERNEL);
  427.         if(!dquot)
  428.             return;
  429.  
  430.         nr_dquots++;
  431.         memset((caddr_t)dquot, 0, sizeof(struct dquot));
  432.         /* all dquots go on the inuse_list */
  433.         put_inuse(dquot);
  434.         put_dquot_head(dquot);
  435.         cnt--;
  436.     }
  437. }
  438.  
  439. static struct dquot *find_best_candidate_weighted(void)
  440. {
  441.     struct list_head *tmp = &free_dquots;
  442.     struct dquot *dquot, *best = NULL;
  443.     unsigned long myscore, bestscore = ~0U;
  444.     int limit = (nr_free_dquots > 128) ? nr_free_dquots >> 2 : 32;
  445.  
  446.     while ((tmp = tmp->next) != &free_dquots && --limit) {
  447.         dquot = list_entry(tmp, struct dquot, dq_free);
  448.         if (dquot->dq_flags & (DQ_LOCKED | DQ_MOD))
  449.             continue;
  450.         myscore = dquot->dq_referenced;
  451.         if (myscore < bestscore) {
  452.             bestscore = myscore;
  453.             best = dquot;
  454.         }
  455.     }
  456.     return best;
  457. }
  458.  
  459. static inline struct dquot *find_best_free(void)
  460. {
  461.     struct list_head *tmp = &free_dquots;
  462.     struct dquot *dquot;
  463.     int limit = (nr_free_dquots > 1024) ? nr_free_dquots >> 5 : 32;
  464.  
  465.     while ((tmp = tmp->next) != &free_dquots && --limit) {
  466.         dquot = list_entry(tmp, struct dquot, dq_free);
  467.         if (dquot->dq_referenced == 0)
  468.             return dquot;
  469.     }
  470.     return NULL;
  471. }
  472.  
  473. struct dquot *get_empty_dquot(void)
  474. {
  475.     struct dquot *dquot;
  476.     int count;
  477.  
  478. repeat:
  479.     dquot = find_best_free();
  480.     if (!dquot)
  481.         goto pressure;
  482. got_it:
  483.     if (dquot->dq_flags & (DQ_LOCKED | DQ_MOD)) {
  484.         wait_on_dquot(dquot);
  485.         if (dquot->dq_flags & DQ_MOD)
  486.         {
  487.             if(dquot->dq_mnt != (struct vfsmount *)NULL)
  488.                 write_dquot(dquot);
  489.         }
  490.         /*
  491.          * The dquot may be back in use now, so we
  492.          * must recheck the free list.
  493.          */
  494.         goto repeat;
  495.     }
  496.     /* sanity check ... */
  497.     if (dquot->dq_count != 0)
  498.         printk(KERN_ERR "VFS: free dquot count=%d\n", dquot->dq_count);
  499.  
  500.     remove_free_dquot(dquot);
  501.     dquot->dq_count = 1;
  502.     /* unhash and selectively clear the structure */
  503.     clear_dquot(dquot);
  504.     return dquot;
  505.  
  506. pressure:
  507.     if (nr_dquots < max_dquots) {
  508.         grow_dquots();
  509.         goto repeat;
  510.     }
  511.  
  512.     dquot = find_best_candidate_weighted();
  513.     if (dquot)
  514.         goto got_it;
  515.     /*
  516.      * Try pruning the dcache to free up some dquots ...
  517.      */
  518.     count = select_dcache(128, 0);
  519.     if (count) {
  520.         printk(KERN_DEBUG "get_empty_dquot: pruning %d\n", count);
  521.         prune_dcache(count);
  522.         free_inode_memory(count);
  523.         goto repeat;
  524.     }
  525.  
  526.     printk("VFS: No free dquots, contact mvw@planets.elm.net\n");
  527.     sleep_on(&dquot_wait);
  528.     goto repeat;
  529. }
  530.  
  531. struct dquot *dqget(kdev_t dev, unsigned int id, short type)
  532. {
  533.     unsigned int hashent = hashfn(dev, id, type);
  534.     struct dquot *dquot, *empty = NULL;
  535.     struct vfsmount *vfsmnt;
  536.  
  537.         if ((vfsmnt = lookup_vfsmnt(dev)) == (struct vfsmount *)NULL || is_enabled(vfsmnt, type) == 0)
  538.                 return(NODQUOT);
  539.  
  540. we_slept:
  541.     if ((dquot = find_dquot(hashent, dev, id, type)) == NULL) {
  542.         if (empty == NULL) {
  543.             dquot_updating[hashent]++;
  544.             empty = get_empty_dquot();
  545.             if (!--dquot_updating[hashent])
  546.                 wake_up(&update_wait);
  547.             goto we_slept;
  548.         }
  549.         dquot = empty;
  550.             dquot->dq_id = id;
  551.             dquot->dq_type = type;
  552.             dquot->dq_dev = dev;
  553.             dquot->dq_mnt = vfsmnt;
  554.         /* hash it first so it can be found */
  555.         hash_dquot(dquot);
  556.             read_dquot(dquot);
  557.     } else {
  558.         if (!dquot->dq_count++) {
  559.             remove_free_dquot(dquot);
  560.         } else
  561.             dqstats.cache_hits++;
  562.         wait_on_dquot(dquot);
  563.         if (empty)
  564.             dqput(empty);
  565.     }
  566.  
  567.     while (dquot_updating[hashent])
  568.         sleep_on(&update_wait);
  569.  
  570.     dquot->dq_referenced++;
  571.     dqstats.lookups++;
  572.  
  573.     return dquot;
  574. }
  575.  
  576. static void add_dquot_ref(kdev_t dev, short type)
  577. {
  578.     struct super_block *sb = get_super(dev);
  579.     struct file *filp;
  580.     struct inode *inode;
  581.  
  582.     if (!sb || !sb->dq_op)
  583.         return;    /* nothing to do */
  584.  
  585.     for (filp = inuse_filps; filp; filp = filp->f_next) {
  586.         if (!filp->f_dentry)
  587.             continue;
  588.         if (filp->f_dentry->d_sb != sb)
  589.             continue;
  590.         inode = filp->f_dentry->d_inode;
  591.         if (!inode)
  592.             continue;
  593.         /* N.B. race problem -- filp could become unused */
  594.         if (filp->f_mode & FMODE_WRITE) {
  595.             sb->dq_op->initialize(inode, type);
  596.             inode->i_flags |= S_QUOTA;
  597.         }
  598.     }
  599. }
  600.  
  601. static void reset_dquot_ptrs(kdev_t dev, short type)
  602. {
  603.     struct super_block *sb = get_super(dev);
  604.     struct file *filp;
  605.     struct inode *inode;
  606.     struct dquot *dquot;
  607.     int cnt;
  608.  
  609.     if (!sb || !sb->dq_op)
  610.         return;    /* nothing to do */
  611.  
  612. restart:
  613.     /* free any quota for unused dentries */
  614.     shrink_dcache_sb(sb);
  615.  
  616.     for (filp = inuse_filps; filp; filp = filp->f_next) {
  617.         if (!filp->f_dentry)
  618.             continue;
  619.         if (filp->f_dentry->d_sb != sb)
  620.             continue;
  621.         inode = filp->f_dentry->d_inode;
  622.         if (!inode)
  623.             continue;
  624.         /*
  625.          * Note: we restart after each blocking operation,
  626.          * as the inuse_filps list may have changed.
  627.          */
  628.         if (IS_QUOTAINIT(inode)) {
  629.             dquot = inode->i_dquot[type];
  630.             inode->i_dquot[type] = NODQUOT;
  631.             /* any other quota in use? */
  632.             for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
  633.                 if (inode->i_dquot[cnt] != NODQUOT)
  634.                     goto put_it;
  635.             }
  636.             inode->i_flags &= ~S_QUOTA;
  637.         put_it:
  638.             if (dquot != NODQUOT) {
  639.                 dqput(dquot);
  640.                 /* we may have blocked ... */
  641.                 goto restart;
  642.             }
  643.         }
  644.     }
  645. }
  646.  
  647. static inline void dquot_incr_inodes(struct dquot *dquot, unsigned long number)
  648. {
  649.     lock_dquot(dquot);
  650.     dquot->dq_curinodes += number;
  651.     dquot->dq_flags |= DQ_MOD;
  652.     unlock_dquot(dquot);
  653. }
  654.  
  655. static inline void dquot_incr_blocks(struct dquot *dquot, unsigned long number)
  656. {
  657.     lock_dquot(dquot);
  658.     dquot->dq_curblocks += number;
  659.     dquot->dq_flags |= DQ_MOD;
  660.     unlock_dquot(dquot);
  661. }
  662.  
  663. static inline void dquot_decr_inodes(struct dquot *dquot, unsigned long number)
  664. {
  665.     lock_dquot(dquot);
  666.     if (dquot->dq_curinodes > number)
  667.         dquot->dq_curinodes -= number;
  668.     else
  669.         dquot->dq_curinodes = 0;
  670.     if (dquot->dq_curinodes < dquot->dq_isoftlimit)
  671.         dquot->dq_itime = (time_t) 0;
  672.     dquot->dq_flags &= ~DQ_INODES;
  673.     dquot->dq_flags |= DQ_MOD;
  674.     unlock_dquot(dquot);
  675. }
  676.  
  677. static inline void dquot_decr_blocks(struct dquot *dquot, unsigned long number)
  678. {
  679.     lock_dquot(dquot);
  680.     if (dquot->dq_curblocks > number)
  681.         dquot->dq_curblocks -= number;
  682.     else
  683.         dquot->dq_curblocks = 0;
  684.     if (dquot->dq_curblocks < dquot->dq_bsoftlimit)
  685.         dquot->dq_btime = (time_t) 0;
  686.     dquot->dq_flags &= ~DQ_BLKS;
  687.     dquot->dq_flags |= DQ_MOD;
  688.     unlock_dquot(dquot);
  689. }
  690.  
  691. static inline char need_print_warning(short type, uid_t initiator, struct dquot *dquot)
  692. {
  693.     switch (type) {
  694.         case USRQUOTA:
  695.             return(initiator == dquot->dq_id);
  696.         case GRPQUOTA:
  697.             return(initiator == dquot->dq_id);
  698.     }
  699.     return(0);
  700. }
  701.  
  702. static inline char ignore_hardlimit(struct dquot *dquot, uid_t initiator)
  703. {
  704.     return(initiator == 0 && dquot->dq_mnt->mnt_dquot.rsquash[dquot->dq_type] == 0);
  705. }
  706.  
  707. static int check_idq(struct dquot *dquot, short type, u_long short inodes, uid_t initiator, 
  708.             struct tty_struct *tty)
  709. {
  710.     if (inodes <= 0 || dquot->dq_flags & DQ_FAKE)
  711.         return(QUOTA_OK);
  712.  
  713.     if (dquot->dq_ihardlimit &&
  714.        (dquot->dq_curinodes + inodes) > dquot->dq_ihardlimit &&
  715.             !ignore_hardlimit(dquot, initiator)) {
  716.         if ((dquot->dq_flags & DQ_INODES) == 0 &&
  717.                      need_print_warning(type, initiator, dquot)) {
  718.             sprintf(quotamessage, "%s: write failed, %s file limit reached\n",
  719.                     dquot->dq_mnt->mnt_dirname, quotatypes[type]);
  720.             tty_write_message(tty, quotamessage);
  721.             dquot->dq_flags |= DQ_INODES;
  722.         }
  723.         return(NO_QUOTA);
  724.     }
  725.  
  726.     if (dquot->dq_isoftlimit &&
  727.        (dquot->dq_curinodes + inodes) > dquot->dq_isoftlimit &&
  728.         dquot->dq_itime && CURRENT_TIME >= dquot->dq_itime &&
  729.             !ignore_hardlimit(dquot, initiator)) {
  730.                 if (need_print_warning(type, initiator, dquot)) {
  731.             sprintf(quotamessage, "%s: warning, %s file quota exceeded too long.\n",
  732.                     dquot->dq_mnt->mnt_dirname, quotatypes[type]);
  733.             tty_write_message(tty, quotamessage);
  734.         }
  735.         return(NO_QUOTA);
  736.     }
  737.  
  738.     if (dquot->dq_isoftlimit &&
  739.        (dquot->dq_curinodes + inodes) > dquot->dq_isoftlimit &&
  740.         dquot->dq_itime == 0) {
  741.                 if (need_print_warning(type, initiator, dquot)) {
  742.             sprintf(quotamessage, "%s: warning, %s file quota exceeded\n",
  743.                     dquot->dq_mnt->mnt_dirname, quotatypes[type]);
  744.             tty_write_message(tty, quotamessage);
  745.         }
  746.         dquot->dq_itime = CURRENT_TIME + dquot->dq_mnt->mnt_dquot.inode_expire[type];
  747.     }
  748.  
  749.     return(QUOTA_OK);
  750. }
  751.  
  752. static int check_bdq(struct dquot *dquot, short type, u_long blocks, uid_t initiator, 
  753.             struct tty_struct *tty, char warn)
  754. {
  755.     if (blocks <= 0 || dquot->dq_flags & DQ_FAKE)
  756.         return(QUOTA_OK);
  757.  
  758.     if (dquot->dq_bhardlimit &&
  759.        (dquot->dq_curblocks + blocks) > dquot->dq_bhardlimit &&
  760.             !ignore_hardlimit(dquot, initiator)) {
  761.         if (warn && (dquot->dq_flags & DQ_BLKS) == 0 &&
  762.                      need_print_warning(type, initiator, dquot)) {
  763.             sprintf(quotamessage, "%s: write failed, %s disk limit reached.\n",
  764.                     dquot->dq_mnt->mnt_dirname, quotatypes[type]);
  765.             tty_write_message(tty, quotamessage);
  766.             dquot->dq_flags |= DQ_BLKS;
  767.         }
  768.         return(NO_QUOTA);
  769.     }
  770.  
  771.     if (dquot->dq_bsoftlimit &&
  772.        (dquot->dq_curblocks + blocks) > dquot->dq_bsoftlimit &&
  773.         dquot->dq_btime && CURRENT_TIME >= dquot->dq_btime &&
  774.             !ignore_hardlimit(dquot, initiator)) {
  775.                 if (warn && need_print_warning(type, initiator, dquot)) {
  776.             sprintf(quotamessage, "%s: write failed, %s disk quota exceeded too long.\n",
  777.                     dquot->dq_mnt->mnt_dirname, quotatypes[type]);
  778.             tty_write_message(tty, quotamessage);
  779.         }
  780.         return(NO_QUOTA);
  781.     }
  782.  
  783.     if (dquot->dq_bsoftlimit &&
  784.        (dquot->dq_curblocks + blocks) > dquot->dq_bsoftlimit &&
  785.         dquot->dq_btime == 0) {
  786.                 if (warn && need_print_warning(type, initiator, dquot)) {
  787.             sprintf(quotamessage, "%s: warning, %s disk quota exceeded\n",
  788.                     dquot->dq_mnt->mnt_dirname, quotatypes[type]);
  789.             tty_write_message(tty, quotamessage);
  790.         }
  791.         dquot->dq_btime = CURRENT_TIME + dquot->dq_mnt->mnt_dquot.block_expire[type];
  792.     }
  793.  
  794.     return(QUOTA_OK);
  795. }
  796.  
  797. /*
  798.  * Initialize a dquot-struct with new quota info. This is used by the
  799.  * system call interface functions.
  800.  */ 
  801. static int set_dqblk(kdev_t dev, int id, short type, int flags, struct dqblk *dqblk)
  802. {
  803.     struct dquot *dquot;
  804.     int error = -EFAULT;
  805.     struct dqblk dq_dqblk;
  806.  
  807.     if (dqblk == (struct dqblk *)NULL)
  808.         return error;
  809.  
  810.     if (flags & QUOTA_SYSCALL) {
  811.         if (copy_from_user(&dq_dqblk, dqblk, sizeof(struct dqblk)))
  812.             return(error);
  813.     } else
  814.         memcpy((caddr_t)&dq_dqblk, (caddr_t)dqblk, sizeof(struct dqblk));
  815.  
  816.     if ((dquot = dqget(dev, id, type)) != NODQUOT) {
  817.         lock_dquot(dquot);
  818.  
  819.         if (id > 0 && ((flags & SET_QUOTA) || (flags & SET_QLIMIT))) {
  820.             dquot->dq_bhardlimit = dq_dqblk.dqb_bhardlimit;
  821.             dquot->dq_bsoftlimit = dq_dqblk.dqb_bsoftlimit;
  822.             dquot->dq_ihardlimit = dq_dqblk.dqb_ihardlimit;
  823.             dquot->dq_isoftlimit = dq_dqblk.dqb_isoftlimit;
  824.         }
  825.  
  826.         if ((flags & SET_QUOTA) || (flags & SET_USE)) {
  827.             if (dquot->dq_isoftlimit &&
  828.                 dquot->dq_curinodes < dquot->dq_isoftlimit &&
  829.                 dq_dqblk.dqb_curinodes >= dquot->dq_isoftlimit)
  830.                 dquot->dq_itime = CURRENT_TIME + dquot->dq_mnt->mnt_dquot.inode_expire[type];
  831.             dquot->dq_curinodes = dq_dqblk.dqb_curinodes;
  832.             if (dquot->dq_curinodes < dquot->dq_isoftlimit)
  833.                 dquot->dq_flags &= ~DQ_INODES;
  834.             if (dquot->dq_bsoftlimit &&
  835.                 dquot->dq_curblocks < dquot->dq_bsoftlimit &&
  836.                 dq_dqblk.dqb_curblocks >= dquot->dq_bsoftlimit)
  837.                 dquot->dq_btime = CURRENT_TIME + dquot->dq_mnt->mnt_dquot.block_expire[type];
  838.             dquot->dq_curblocks = dq_dqblk.dqb_curblocks;
  839.             if (dquot->dq_curblocks < dquot->dq_bsoftlimit)
  840.                 dquot->dq_flags &= ~DQ_BLKS;
  841.         }
  842.  
  843.         if (id == 0) {
  844.             dquot->dq_mnt->mnt_dquot.block_expire[type] = dquot->dq_btime = dq_dqblk.dqb_btime;
  845.             dquot->dq_mnt->mnt_dquot.inode_expire[type] = dquot->dq_itime = dq_dqblk.dqb_itime;
  846.         }
  847.  
  848.         if (dq_dqblk.dqb_bhardlimit == 0 && dq_dqblk.dqb_bsoftlimit == 0 &&
  849.             dq_dqblk.dqb_ihardlimit == 0 && dq_dqblk.dqb_isoftlimit == 0)
  850.             dquot->dq_flags |= DQ_FAKE;
  851.         else
  852.             dquot->dq_flags &= ~DQ_FAKE;
  853.  
  854.         dquot->dq_flags |= DQ_MOD;
  855.         unlock_dquot(dquot);
  856.         dqput(dquot);
  857.     }
  858.     return(0);
  859. }
  860.  
  861. static int get_quota(kdev_t dev, int id, short type, struct dqblk *dqblk)
  862. {
  863.     struct dquot *dquot;
  864.     int error = -ESRCH;
  865.  
  866.     if (!dev_has_quota_enabled(dev, type))
  867.         goto out;
  868.     dquot = dqget(dev, id, type);
  869.     if (dquot == NODQUOT)
  870.         goto out;
  871.  
  872.     error = -EFAULT;
  873.     if (dqblk && !copy_to_user(dqblk, &dquot->dq_dqb, sizeof(struct dqblk)))
  874.         error = 0;
  875.     dqput(dquot);
  876. out:
  877.     return error;
  878. }
  879.  
  880. static int get_stats(caddr_t addr)
  881. {
  882.     int error = -EFAULT;
  883.     struct dqstats stats;
  884.  
  885.     dqstats.allocated_dquots = nr_dquots;
  886.     dqstats.free_dquots = nr_free_dquots;
  887.  
  888.     /* make a copy, in case we page-fault in user space */
  889.     memcpy(&stats, &dqstats, sizeof(struct dqstats));
  890.     if (!copy_to_user(addr, &stats, sizeof(struct dqstats)))
  891.         error = 0;
  892.     return error;
  893. }
  894.  
  895. static int quota_root_squash(kdev_t dev, short type, int *addr)
  896. {
  897.     struct vfsmount *vfsmnt;
  898.     int new_value, error;
  899.  
  900.     if ((vfsmnt = lookup_vfsmnt(dev)) == (struct vfsmount *)NULL)
  901.         return(-ENODEV);
  902.  
  903.     error = -EFAULT;
  904.     if (!copy_from_user(&new_value, addr, sizeof(int))) {
  905.         vfsmnt->mnt_dquot.rsquash[type] = new_value;
  906.         error = 0;
  907.     }
  908.     return error;
  909. }
  910.  
  911. /*
  912.  * This is a simple algorithm that calculates the size of a file in blocks.
  913.  * This is only used on filesystems that do not have an i_blocks count.
  914.  */
  915. static u_long isize_to_blocks(size_t isize, size_t blksize)
  916. {
  917.     u_long blocks;
  918.     u_long indirect;
  919.  
  920.     if (!blksize)
  921.         blksize = BLOCK_SIZE;
  922.     blocks = (isize / blksize) + ((isize % blksize) ? 1 : 0);
  923.     if (blocks > 10) {
  924.         indirect = ((blocks - 11) >> 8) + 1; /* single indirect blocks */
  925.         if (blocks > (10 + 256)) {
  926.             indirect += ((blocks - 267) >> 16) + 1; /* double indirect blocks */
  927.             if (blocks > (10 + 256 + (256 << 8)))
  928.                 indirect++; /* triple indirect blocks */
  929.         }
  930.         blocks += indirect;
  931.     }
  932.     return(blocks);
  933. }
  934.  
  935. /*
  936.  * Externally referenced functions through dquot_operations in inode.
  937.  *
  938.  * Note: this is a blocking operation.
  939.  */
  940. void dquot_initialize(struct inode *inode, short type)
  941. {
  942.     struct dquot *dquot;
  943.     unsigned int id = 0;
  944.     short cnt;
  945.  
  946.     if (S_ISREG(inode->i_mode) ||
  947.             S_ISDIR(inode->i_mode) ||
  948.             S_ISLNK(inode->i_mode)) {
  949.         for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
  950.             if (type != -1 && cnt != type)
  951.                 continue;
  952.  
  953.             if (!sb_has_quota_enabled(inode->i_sb, cnt))
  954.                 continue;
  955.  
  956.             if (inode->i_dquot[cnt] == NODQUOT) {
  957.                 switch (cnt) {
  958.                     case USRQUOTA:
  959.                         id = inode->i_uid;
  960.                         break;
  961.                     case GRPQUOTA:
  962.                         id = inode->i_gid;
  963.                         break;
  964.                 }
  965.                 dquot = dqget(inode->i_dev, id, cnt);
  966.                 if (inode->i_dquot[cnt] != NODQUOT) {
  967.                     dqput(dquot);
  968.                     continue;
  969.                 } 
  970.                 inode->i_dquot[cnt] = dquot;
  971.                 inode->i_flags |= S_QUOTA;
  972.             }
  973.         }
  974.     }
  975. }
  976.  
  977. /*
  978.  * Release all quota for the specified inode.
  979.  *
  980.  * Note: this is a blocking operation.
  981.  */
  982. void dquot_drop(struct inode *inode)
  983. {
  984.     struct dquot *dquot;
  985.     short cnt;
  986.  
  987.     inode->i_flags &= ~S_QUOTA;
  988.     for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
  989.         if (inode->i_dquot[cnt] == NODQUOT)
  990.             continue;
  991.         dquot = inode->i_dquot[cnt];
  992.         inode->i_dquot[cnt] = NODQUOT;
  993.         dqput(dquot);
  994.     }
  995. }
  996.  
  997. /*
  998.  * Note: this is a blocking operation.
  999.  */
  1000. int dquot_alloc_block(const struct inode *inode, unsigned long number, uid_t initiator, 
  1001.             char warn)
  1002. {
  1003.     unsigned short cnt;
  1004.     struct tty_struct *tty = current->tty;
  1005.  
  1006.     for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
  1007.         if (inode->i_dquot[cnt] == NODQUOT)
  1008.             continue;
  1009.         if (check_bdq(inode->i_dquot[cnt], cnt, number, initiator, tty, warn))
  1010.             return(NO_QUOTA);
  1011.     }
  1012.  
  1013.     for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
  1014.         if (inode->i_dquot[cnt] == NODQUOT)
  1015.             continue;
  1016.         dquot_incr_blocks(inode->i_dquot[cnt], number);
  1017.     }
  1018.  
  1019.     return(QUOTA_OK);
  1020. }
  1021.  
  1022. /*
  1023.  * Note: this is a blocking operation.
  1024.  */
  1025. int dquot_alloc_inode(const struct inode *inode, unsigned long number, uid_t initiator)
  1026. {
  1027.     unsigned short cnt;
  1028.     struct tty_struct *tty = current->tty;
  1029.  
  1030.     for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
  1031.         if (inode->i_dquot[cnt] == NODQUOT)
  1032.             continue;
  1033.         if (check_idq(inode->i_dquot[cnt], cnt, number, initiator, tty))
  1034.             return(NO_QUOTA);
  1035.     }
  1036.  
  1037.     for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
  1038.         if (inode->i_dquot[cnt] == NODQUOT)
  1039.             continue;
  1040.         dquot_incr_inodes(inode->i_dquot[cnt], number);
  1041.     }
  1042.  
  1043.     return(QUOTA_OK);
  1044. }
  1045.  
  1046. /*
  1047.  * Note: this is a blocking operation.
  1048.  */
  1049. void dquot_free_block(const struct inode *inode, unsigned long number)
  1050. {
  1051.     unsigned short cnt;
  1052.  
  1053.     for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
  1054.         if (inode->i_dquot[cnt] == NODQUOT)
  1055.             continue;
  1056.         dquot_decr_blocks(inode->i_dquot[cnt], number);
  1057.     }
  1058. }
  1059.  
  1060. /*
  1061.  * Note: this is a blocking operation.
  1062.  */
  1063. void dquot_free_inode(const struct inode *inode, unsigned long number)
  1064. {
  1065.     unsigned short cnt;
  1066.  
  1067.     for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
  1068.         if (inode->i_dquot[cnt] == NODQUOT)
  1069.             continue;
  1070.         dquot_decr_inodes(inode->i_dquot[cnt], number);
  1071.     }
  1072. }
  1073.  
  1074. /*
  1075.  * Transfer the number of inode and blocks from one diskquota to an other.
  1076.  *
  1077.  * Note: this is a blocking operation.
  1078.  */
  1079. int dquot_transfer(struct inode *inode, struct iattr *iattr, char direction, uid_t initiator)
  1080. {
  1081.     unsigned long blocks;
  1082.     struct dquot *transfer_from[MAXQUOTAS];
  1083.     struct dquot *transfer_to[MAXQUOTAS];
  1084.     struct tty_struct *tty = current->tty;
  1085.     short cnt, disc;
  1086.  
  1087.     /*
  1088.      * Find out if this filesystem uses i_blocks.
  1089.      */
  1090.     if (inode->i_blksize == 0)
  1091.         blocks = isize_to_blocks(inode->i_size, BLOCK_SIZE);
  1092.     else
  1093.         blocks = (inode->i_blocks / 2);
  1094.  
  1095.     /*
  1096.      * Build the transfer_from and transfer_to lists and check quotas to see
  1097.      * if operation is permitted.
  1098.      */
  1099.     for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
  1100.         transfer_from[cnt] = NODQUOT;
  1101.         transfer_to[cnt] = NODQUOT;
  1102.  
  1103.         if (!sb_has_quota_enabled(inode->i_sb, cnt))
  1104.             continue;
  1105.  
  1106.         switch (cnt) {
  1107.             case USRQUOTA:
  1108.                 if (inode->i_uid == iattr->ia_uid)
  1109.                     continue;
  1110.                 transfer_from[cnt] = dqget(inode->i_dev, (direction) ? iattr->ia_uid : inode->i_uid, cnt);
  1111.                 transfer_to[cnt] = dqget(inode->i_dev, (direction) ? inode->i_uid : iattr->ia_uid, cnt);
  1112.                 break;
  1113.             case GRPQUOTA:
  1114.                 if (inode->i_gid == iattr->ia_gid)
  1115.                     continue;
  1116.                 transfer_from[cnt] = dqget(inode->i_dev, (direction) ? iattr->ia_gid : inode->i_gid, cnt);
  1117.                 transfer_to[cnt] = dqget(inode->i_dev, (direction) ? inode->i_gid : iattr->ia_gid, cnt);
  1118.                 break;
  1119.         }
  1120.  
  1121.         if (check_idq(transfer_to[cnt], cnt, 1, initiator, tty) == NO_QUOTA ||
  1122.             check_bdq(transfer_to[cnt], cnt, blocks, initiator, tty, 0) == NO_QUOTA) {
  1123.             for (disc = 0; disc <= cnt; disc++) {
  1124.                 dqput(transfer_from[disc]);
  1125.                 dqput(transfer_to[disc]);
  1126.             }
  1127.             return(NO_QUOTA);
  1128.         }
  1129.     }
  1130.  
  1131.     /*
  1132.      * Finally perform the needed transfer from transfer_from to transfer_to,
  1133.      * and release any pointers to dquots not needed anymore.
  1134.      */
  1135.     for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
  1136.         /*
  1137.          * Skip changes for same uid or gid or for non-existing quota-type.
  1138.          */
  1139.         if (transfer_from[cnt] == NODQUOT && transfer_to[cnt] == NODQUOT)
  1140.             continue;
  1141.  
  1142.         if (transfer_from[cnt] != NODQUOT) {
  1143.             dquot_decr_inodes(transfer_from[cnt], 1);
  1144.             dquot_decr_blocks(transfer_from[cnt], blocks);
  1145.         }
  1146.  
  1147.         if (transfer_to[cnt] != NODQUOT) {
  1148.             dquot_incr_inodes(transfer_to[cnt], 1);
  1149.             dquot_incr_blocks(transfer_to[cnt], blocks);
  1150.         }
  1151.  
  1152.         if (inode->i_dquot[cnt] != NODQUOT) {
  1153.             struct dquot *temp = inode->i_dquot[cnt];
  1154.             inode->i_dquot[cnt] = transfer_to[cnt];
  1155.             dqput(temp);
  1156.             dqput(transfer_from[cnt]);
  1157.         } else {
  1158.             dqput(transfer_from[cnt]);
  1159.             dqput(transfer_to[cnt]);
  1160.         }
  1161.     }
  1162.  
  1163.     return(QUOTA_OK);
  1164. }
  1165.  
  1166.  
  1167. void __init dquot_init_hash(void)
  1168. {
  1169.     printk(KERN_NOTICE "VFS: Diskquotas version %s initialized\n", __DQUOT_VERSION__);
  1170.  
  1171.     dquot_cachep = kmem_cache_create("dquot", sizeof(struct dquot),
  1172.                      sizeof(unsigned long) * 4,
  1173.                      SLAB_HWCACHE_ALIGN, NULL, NULL);
  1174.  
  1175.     if (!dquot_cachep)
  1176.         panic("Cannot create dquot SLAB cache\n");
  1177.  
  1178.     memset(dquot_hash, 0, sizeof(dquot_hash));
  1179.     memset((caddr_t)&dqstats, 0, sizeof(dqstats));
  1180. }
  1181.  
  1182. /*
  1183.  * Definitions of diskquota operations.
  1184.  */
  1185. struct dquot_operations dquot_operations = {
  1186.     dquot_initialize,        /* mandatory */
  1187.     dquot_drop,            /* mandatory */
  1188.     dquot_alloc_block,
  1189.     dquot_alloc_inode,
  1190.     dquot_free_block,
  1191.     dquot_free_inode,
  1192.     dquot_transfer
  1193. };
  1194.  
  1195. static inline void set_enable_flags(struct vfsmount *vfsmnt, short type)
  1196. {
  1197.     switch (type) {
  1198.         case USRQUOTA:
  1199.             vfsmnt->mnt_dquot.flags |= DQUOT_USR_ENABLED;
  1200.             break;
  1201.         case GRPQUOTA:
  1202.             vfsmnt->mnt_dquot.flags |= DQUOT_GRP_ENABLED;
  1203.             break;
  1204.     }
  1205. }
  1206.  
  1207. static inline void reset_enable_flags(struct vfsmount *vfsmnt, short type)
  1208. {
  1209.     switch (type) {
  1210.         case USRQUOTA:
  1211.             vfsmnt->mnt_dquot.flags &= ~DQUOT_USR_ENABLED;
  1212.             break;
  1213.         case GRPQUOTA:
  1214.             vfsmnt->mnt_dquot.flags &= ~DQUOT_GRP_ENABLED;
  1215.             break;
  1216.     }
  1217. }
  1218.  
  1219. /*
  1220.  * Turn quota off on a device. type == -1 ==> quotaoff for all types (umount)
  1221.  */
  1222. int quota_off(kdev_t dev, short type)
  1223. {
  1224.     struct vfsmount *vfsmnt;
  1225.     struct file *filp;
  1226.     short cnt;
  1227.  
  1228.     for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
  1229.         if (type != -1 && cnt != type)
  1230.             continue;
  1231.  
  1232.         vfsmnt = lookup_vfsmnt(dev);
  1233.         if (!vfsmnt)
  1234.             goto out;
  1235.                 if (!vfsmnt->mnt_sb)
  1236.             goto out;
  1237.         if (!is_enabled(vfsmnt, cnt))
  1238.             continue;
  1239.         reset_enable_flags(vfsmnt, cnt);
  1240.  
  1241.         /* Note: these are blocking operations */
  1242.         reset_dquot_ptrs(dev, cnt);
  1243.         invalidate_dquots(dev, cnt);
  1244.  
  1245.         filp = vfsmnt->mnt_dquot.files[cnt];
  1246.         vfsmnt->mnt_dquot.files[cnt] = (struct file *)NULL;
  1247.         vfsmnt->mnt_dquot.inode_expire[cnt] = 0;
  1248.         vfsmnt->mnt_dquot.block_expire[cnt] = 0;
  1249.         fput(filp);
  1250.     }
  1251.  
  1252.     /*
  1253.      * Check whether any quota is still enabled,
  1254.      * and if not clear the dq_op pointer.
  1255.      */
  1256.     vfsmnt = lookup_vfsmnt(dev);
  1257.     if (vfsmnt && vfsmnt->mnt_sb) {
  1258.         int enabled = 0;
  1259.         for (cnt = 0; cnt < MAXQUOTAS; cnt++)
  1260.             enabled |= is_enabled(vfsmnt, cnt);
  1261.         if (!enabled)
  1262.             vfsmnt->mnt_sb->dq_op = NULL;
  1263.     }
  1264.  
  1265. out:
  1266.     return(0);
  1267. }
  1268.  
  1269. int quota_on(kdev_t dev, short type, char *path)
  1270. {
  1271.     struct file *filp = NULL;
  1272.     struct dentry *dentry;
  1273.     struct vfsmount *vfsmnt;
  1274.     struct inode *inode;
  1275.     struct dquot *dquot;
  1276.     char *tmp;
  1277.     int error;
  1278.  
  1279.     vfsmnt = lookup_vfsmnt(dev);
  1280.     if (vfsmnt == (struct vfsmount *)NULL)
  1281.         return -ENODEV;
  1282.  
  1283.     if (is_enabled(vfsmnt, type))
  1284.         return(-EBUSY);
  1285.  
  1286.     tmp = getname(path);
  1287.     error = PTR_ERR(tmp);
  1288.     if (IS_ERR(tmp))
  1289.         return error;
  1290.  
  1291.     dentry = open_namei(tmp, O_RDWR, 0600);
  1292.     putname(tmp);
  1293.  
  1294.     error = PTR_ERR(dentry);
  1295.     if (IS_ERR(dentry))
  1296.         return error;
  1297.     inode = dentry->d_inode;
  1298.  
  1299.     if (!S_ISREG(inode->i_mode)) {
  1300.         dput(dentry);
  1301.         return -EACCES;
  1302.     }
  1303.  
  1304.     if (inode->i_size == 0 || (inode->i_size % sizeof(struct dqblk)) != 0) {
  1305.         dput(dentry);
  1306.         return(-EINVAL);
  1307.     }
  1308.  
  1309.     filp = get_empty_filp();
  1310.     if (filp != (struct file *)NULL) {
  1311.         filp->f_mode = (O_RDWR + 1) & O_ACCMODE;
  1312.         filp->f_flags = O_RDWR;
  1313.         filp->f_dentry = dentry;
  1314.         filp->f_pos = 0;
  1315.         filp->f_reada = 0;
  1316.         filp->f_op = inode->i_op->default_file_ops;
  1317.         if (filp->f_op->read || filp->f_op->write) {
  1318.             error = get_write_access(inode);
  1319.             if (!error) {
  1320.                 if (filp->f_op && filp->f_op->open)
  1321.                     error = filp->f_op->open(inode, filp);
  1322.                 if (!error) {
  1323.                     set_enable_flags(vfsmnt, type);
  1324.                     vfsmnt->mnt_dquot.files[type] = filp;
  1325.  
  1326.                     dquot = dqget(dev, 0, type);
  1327.                     vfsmnt->mnt_dquot.inode_expire[type] = (dquot) ? dquot->dq_itime : MAX_IQ_TIME;
  1328.                     vfsmnt->mnt_dquot.block_expire[type] = (dquot) ? dquot->dq_btime : MAX_DQ_TIME;
  1329.                     dqput(dquot);
  1330.  
  1331.                     vfsmnt->mnt_sb->dq_op = &dquot_operations;
  1332.                     add_dquot_ref(dev, type);
  1333.  
  1334.                     return(0);
  1335.                 }
  1336.                 put_write_access(inode);
  1337.             }
  1338.         } else
  1339.             error = -EIO;
  1340.         put_filp(filp);
  1341.     } else
  1342.         error = -EMFILE;
  1343.  
  1344.     dput(dentry);
  1345.  
  1346.     return(error);
  1347. }
  1348.  
  1349. /*
  1350.  * This is the system call interface. This communicates with
  1351.  * the user-level programs. Currently this only supports diskquota
  1352.  * calls. Maybe we need to add the process quotas etc. in the future,
  1353.  * but we probably should use rlimits for that.
  1354.  */
  1355. asmlinkage int sys_quotactl(int cmd, const char *special, int id, caddr_t addr)
  1356. {
  1357.     int cmds = 0, type = 0, flags = 0;
  1358.     kdev_t dev;
  1359.     int ret = -EINVAL;
  1360.  
  1361.     lock_kernel();
  1362.     cmds = cmd >> SUBCMDSHIFT;
  1363.     type = cmd & SUBCMDMASK;
  1364.  
  1365.     if ((u_int) type >= MAXQUOTAS)
  1366.         goto out;
  1367.     ret = -EPERM;
  1368.     switch (cmds) {
  1369.         case Q_SYNC:
  1370.         case Q_GETSTATS:
  1371.             break;
  1372.         case Q_GETQUOTA:
  1373.             if (((type == USRQUOTA && current->uid != id) ||
  1374.                  (type == GRPQUOTA && current->gid != id)) &&
  1375.                 !capable(CAP_SYS_RESOURCE))
  1376.                 goto out;
  1377.             break;
  1378.         default:
  1379.             if (!capable(CAP_SYS_RESOURCE))
  1380.                 goto out;
  1381.     }
  1382.  
  1383.     ret = -EINVAL;
  1384.     dev = 0;
  1385.     if (special != NULL || (cmds != Q_SYNC && cmds != Q_GETSTATS)) {
  1386.         mode_t mode;
  1387.         struct dentry * dentry;
  1388.  
  1389.         dentry = namei(special);
  1390.         if (IS_ERR(dentry))
  1391.             goto out;
  1392.  
  1393.         dev = dentry->d_inode->i_rdev;
  1394.         mode = dentry->d_inode->i_mode;
  1395.         dput(dentry);
  1396.  
  1397.         ret = -ENOTBLK;
  1398.         if (!S_ISBLK(mode))
  1399.             goto out;
  1400.     }
  1401.  
  1402.     ret = -EINVAL;
  1403.     switch (cmds) {
  1404.         case Q_QUOTAON:
  1405.             ret = quota_on(dev, type, (char *) addr);
  1406.             goto out;
  1407.         case Q_QUOTAOFF:
  1408.             ret = quota_off(dev, type);
  1409.             goto out;
  1410.         case Q_GETQUOTA:
  1411.             ret = get_quota(dev, id, type, (struct dqblk *) addr);
  1412.             goto out;
  1413.         case Q_SETQUOTA:
  1414.             flags |= SET_QUOTA;
  1415.             break;
  1416.         case Q_SETUSE:
  1417.             flags |= SET_USE;
  1418.             break;
  1419.         case Q_SETQLIM:
  1420.             flags |= SET_QLIMIT;
  1421.             break;
  1422.         case Q_SYNC:
  1423.             ret = sync_dquots(dev, type);
  1424.             goto out;
  1425.         case Q_GETSTATS:
  1426.             ret = get_stats(addr);
  1427.             goto out;
  1428.         case Q_RSQUASH:
  1429.             ret = quota_root_squash(dev, type, (int *) addr);
  1430.             goto out;
  1431.         default:
  1432.             goto out;
  1433.     }
  1434.  
  1435.     flags |= QUOTA_SYSCALL;
  1436.  
  1437.     ret = -ESRCH;
  1438.     if (dev_has_quota_enabled(dev, type))
  1439.         ret = set_dqblk(dev, id, type, flags, (struct dqblk *) addr);
  1440. out:
  1441.     unlock_kernel();
  1442.     return ret;
  1443. }
  1444.